gsk: Scale glyphs in the glyph cache
authorMatthias Clasen <mclasen@redhat.com>
Sat, 28 Oct 2017 17:13:31 +0000 (13:13 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 28 Oct 2017 17:13:31 +0000 (13:13 -0400)
Pass a scale factor when caching glyphs or looking them
up in the cache. The glyphs in the cache are rendered
with subpixel precision determined by the scale. Update
all callers to pass a scale factor according to the window
scale. This lets us render crisp glyphs on hidpi systems.

gsk/gskvulkancolortextpipeline.c
gsk/gskvulkancolortextpipelineprivate.h
gsk/gskvulkanglyphcache.c
gsk/gskvulkanglyphcacheprivate.h
gsk/gskvulkanrenderer.c
gsk/gskvulkanrendererprivate.h
gsk/gskvulkanrenderpass.c
gsk/gskvulkantextpipeline.c
gsk/gskvulkantextpipelineprivate.h

index 654b30ccef33216a1aa07276dc80d6c4db14a823..dd236da880bb1393e3a653054772704674334f8c 100644 (file)
@@ -103,7 +103,8 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
                                                     float                       x,
                                                     float                       y,
                                                     guint                       start_glyph,
-                                                    guint                       num_glyphs)
+                                                    guint                       num_glyphs,
+                                                    float                       scale)
 {
   GskVulkanColorTextInstance *instances = (GskVulkanColorTextInstance *) data;
   int i;
@@ -127,7 +128,7 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
               GskVulkanColorTextInstance *instance = &instances[count];
               GskVulkanCachedGlyph *glyph;
 
-              glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph);
+              glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale);
 
               instance->tex_rect[0] = glyph->tx;
               instance->tex_rect[1] = glyph->ty;
index 9a933ef27a0dcbe304e528d10c6142e61a1abf8d..2e46b1c6a884aadf85f30c99bdf23c251dcd0677 100644 (file)
@@ -31,7 +31,8 @@ void                    gsk_vulkan_color_text_pipeline_collect_vertex_data   (Gs
                                                                               float                           x,
                                                                               float                           y,
                                                                               guint                           start_glyph,
-                                                                              guint                           num_glyphs);
+                                                                              guint                           num_glyphs,
+                                                                              float                           scale);
 gsize                   gsk_vulkan_color_text_pipeline_draw                  (GskVulkanColorTextPipeline     *pipeline,
                                                                               VkCommandBuffer                 command_buffer,
                                                                               gsize                           offset,
index 544b26f0b14cbd6ba203323595ac47a861589f35..c326c568db92140a6842267fb4e5c7740f179281 100644 (file)
@@ -116,6 +116,7 @@ gsk_vulkan_glyph_cache_class_init (GskVulkanGlyphCacheClass *klass)
 typedef struct {
   PangoFont *font;
   PangoGlyph glyph;
+  guint scale; /* times 1024 */
 } GlyphCacheKey;
 
 static gboolean
@@ -125,7 +126,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2)
   const GlyphCacheKey *key2 = v2;
 
   return key1->font == key2->font &&
-         key1->glyph == key2->glyph;
+         key1->glyph == key2->glyph &&
+         key1->scale == key2->scale;
 }
 
 static guint
@@ -133,7 +135,7 @@ glyph_cache_hash (gconstpointer v)
 {
   const GlyphCacheKey *key = v;
 
-  return GPOINTER_TO_UINT (key->font) ^ key->glyph;
+  return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale;
 }
 
 static void
@@ -175,6 +177,8 @@ add_to_cache (GskVulkanGlyphCache  *cache,
   Atlas *atlas;
   int i;
   DirtyGlyph *dirty;
+  int width = value->draw_width * key->scale / 1024;
+  int height = value->draw_height * key->scale / 1024;
 
   for (i = 0; i < cache->atlases->len; i++)
     {
@@ -185,14 +189,14 @@ add_to_cache (GskVulkanGlyphCache  *cache,
       y = atlas->y;
       y0 = atlas->y0;
 
-      if (atlas->x + value->draw_width + 1 >= atlas->width)
+      if (atlas->x + width + 1 >= atlas->width)
         {
           /* start a new row */
           y0 = y + 1;
           x = 1;
         }
 
-      if (y0 + value->draw_height + 1 >= atlas->height)
+      if (y0 + height + 1 >= atlas->height)
         continue;
 
       atlas->y0 = y0;
@@ -209,8 +213,8 @@ add_to_cache (GskVulkanGlyphCache  *cache,
 
   value->tx = (float)atlas->x / atlas->width;
   value->ty = (float)atlas->y0 / atlas->height;
-  value->tw = (float)value->draw_width / atlas->width;
-  value->th = (float)value->draw_height / atlas->height;
+  value->tw = (float)width / atlas->width;
+  value->th = (float)height / atlas->height;
 
   value->texture_index = i;
 
@@ -219,8 +223,8 @@ add_to_cache (GskVulkanGlyphCache  *cache,
   dirty->value = value;
   atlas->dirty_glyphs = g_list_prepend (atlas->dirty_glyphs, dirty);
 
-  atlas->x = atlas->x + value->draw_width + 1;
-  atlas->y = MAX (atlas->y, atlas->y0 + value->draw_height + 1);
+  atlas->x = atlas->x + width + 1;
+  atlas->y = MAX (atlas->y, atlas->y0 + height + 1);
 
   atlas->num_glyphs++;
 
@@ -254,8 +258,9 @@ render_glyph (Atlas          *atlas,
   cairo_glyph_t cg;
 
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-                                        value->draw_width,
-                                        value->draw_height);
+                                        value->draw_width * key->scale / 1024,
+                                        value->draw_height * key->scale / 1024);
+  cairo_surface_set_device_scale (surface, key->scale / 1024.0, key->scale / 1024.0);
 
   cr = cairo_create (surface);
 
@@ -324,13 +329,15 @@ GskVulkanCachedGlyph *
 gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
                                gboolean             create,
                                PangoFont           *font,
-                               PangoGlyph           glyph)
+                               PangoGlyph           glyph,
+                               float                scale)
 {
   GlyphCacheKey lookup_key;
   GskVulkanCachedGlyph *value;
 
   lookup_key.font = font;
   lookup_key.glyph = glyph;
+  lookup_key.scale = (guint)(scale * 1024);
 
   value = g_hash_table_lookup (cache->hash_table, &lookup_key);
 
@@ -364,6 +371,7 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
 
       key->font = g_object_ref (font);
       key->glyph = glyph;
+      key->scale = (guint)(scale * 1024);
 
       if (ink_rect.width > 0 && ink_rect.height > 0)
         add_to_cache (cache, key, value);
index 3a9cddfbee3383be5f7df677e27152863e8c1d05..6cf223f27d0526bd6848333527f43a2b44986057 100644 (file)
@@ -20,7 +20,8 @@ GskVulkanImage *     gsk_vulkan_glyph_cache_get_glyph_image (GskVulkanGlyphCache
 GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup         (GskVulkanGlyphCache *cache,
                                                              gboolean             create,
                                                              PangoFont           *font,
-                                                             PangoGlyph           glyph);
+                                                             PangoGlyph           glyph,
+                                                             float                scale);
 
 void                  gsk_vulkan_glyph_cache_begin_frame    (GskVulkanGlyphCache *cache);
 
index fcc339fcd4e3ecaaa56f215eca4b48c5a08d41bc..7bc9431d583cdec0d4beed997ae1ef28759568d4 100644 (file)
@@ -350,9 +350,10 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
 guint
 gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self,
                                  PangoFont         *font,
-                                 PangoGlyph         glyph)
+                                 PangoGlyph         glyph,
+                                 float              scale)
 {
-  return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph)->texture_index;
+  return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, scale)->texture_index;
 }
 
 GskVulkanImage *
@@ -366,7 +367,8 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer  *self,
 GskVulkanCachedGlyph *
 gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
                                       PangoFont         *font,
-                                      PangoGlyph         glyph)
+                                      PangoGlyph         glyph,
+                                      float              scale)
 {
-  return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph);
+  return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, scale);
 }
index 19f0d3baa5c19c224f6eb3532b7085a7c1badfac..d86734c9dfb34451acdcaf816eb29396a9f376cb 100644 (file)
@@ -44,7 +44,8 @@ typedef struct
 
 guint                  gsk_vulkan_renderer_cache_glyph      (GskVulkanRenderer *renderer,
                                                              PangoFont         *font,
-                                                             PangoGlyph         glyph);
+                                                             PangoGlyph         glyph,
+                                                             float              scale);
 
 GskVulkanImage *       gsk_vulkan_renderer_ref_glyph_image  (GskVulkanRenderer *self,
                                                              GskVulkanUploader *uploader,
@@ -52,7 +53,8 @@ GskVulkanImage *       gsk_vulkan_renderer_ref_glyph_image  (GskVulkanRenderer *
 
 GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
                                                              PangoFont         *font,
-                                                             PangoGlyph         glyph);
+                                                             PangoGlyph         glyph,
+                                                             float              scale);
 
 
 G_END_DECLS
index 09ba75634cd7edb16549d0463a43f403f16ef753..00f79bebdf4ee94c85b97dd3a4268f6ef3459eb8 100644 (file)
@@ -90,6 +90,7 @@ struct _GskVulkanOpText
   guint                texture_index; /* index of the texture in the glyph cache */
   guint                start_glyph; /* the first glyph in nodes glyphstring that we render */
   guint                num_glyphs; /* number of *non-empty* glyphs (== instances) we render */
+  float                scale;
 };
 
 struct _GskVulkanOpPushConstants
@@ -406,6 +407,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
 
         op.text.start_glyph = 0;
         op.text.texture_index = G_MAXUINT;
+        op.text.scale = gdk_window_get_scale_factor (gsk_renderer_get_window (GSK_RENDERER (renderer)));
 
         for (i = 0, count = 0; i < num_glyphs; i++)
           {
@@ -413,7 +415,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
 
             if (gi->glyph != PANGO_GLYPH_EMPTY && !(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
               {
-                texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph);
+                texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph, op.text.scale);
                 if (op.text.texture_index == G_MAXUINT)
                   op.text.texture_index = texture_index;
                 if (texture_index != op.text.texture_index)
@@ -1232,7 +1234,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
                                                           gsk_text_node_get_x (op->text.node),
                                                           gsk_text_node_get_y (op->text.node),
                                                           op->text.start_glyph,
-                                                          op->text.num_glyphs);
+                                                          op->text.num_glyphs,
+                                                          op->text.scale);
             n_bytes += op->text.vertex_count;
           }
           break;
@@ -1250,7 +1253,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
                                                                 gsk_text_node_get_x (op->text.node),
                                                                 gsk_text_node_get_y (op->text.node),
                                                                 op->text.start_glyph,
-                                                                op->text.num_glyphs);
+                                                                op->text.num_glyphs,
+                                                                op->text.scale);
             n_bytes += op->text.vertex_count;
           }
           break;
index 5cdeb15a1f75d778e64b3b174a69176e8055d38f..5ca2d7e00c34123676d63aa7aff5081f1e9af40d 100644 (file)
@@ -111,7 +111,8 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline  *pipeline,
                                               float                   x,
                                               float                   y,
                                               guint                   start_glyph,
-                                              guint                   num_glyphs)
+                                              guint                   num_glyphs,
+                                              float                   scale)
 {
   GskVulkanTextInstance *instances = (GskVulkanTextInstance *) data;
   int i;
@@ -135,7 +136,7 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline  *pipeline,
               GskVulkanTextInstance *instance = &instances[count];
               GskVulkanCachedGlyph *glyph;
 
-              glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph);
+              glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale);
 
               instance->tex_rect[0] = glyph->tx;
               instance->tex_rect[1] = glyph->ty;
index 064045e4698bb56cbebb8580ff964cca41d25473..47517de03c7057dbd43073f7209179c46f8edad7 100644 (file)
@@ -32,7 +32,8 @@ void                    gsk_vulkan_text_pipeline_collect_vertex_data   (GskVulka
                                                                         float                           x,
                                                                         float                           y,
                                                                         guint                           start_glyph,
-                                                                        guint                           num_glyphs);
+                                                                        guint                           num_glyphs,
+                                                                        float                           scale);
 gsize                   gsk_vulkan_text_pipeline_draw                  (GskVulkanTextPipeline         *pipeline,
                                                                         VkCommandBuffer                 command_buffer,
                                                                         gsize                           offset,